/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.springBoot.springBootSysCore.modules.entity.utils;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.*;

import com.springBoot.springBootSysCore.common.service.SysBaseService;
import com.springBoot.springBootSysCore.modules.shiro.SystemAuthorizingRealm;
import com.springBoot.springBootSysCore.modules.shiro.stateles.StatelessRealm;
import com.springBoot.springBootSysCore.modules.shiro.stateles.StatelessToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.data.jpa.domain.Specification;

import com.springBoot.springBootSysCore.common.utils.CacheUtils;
import com.springBoot.springBootSysCore.common.utils.SpringContextHolder;
import com.springBoot.springBootSysCore.modules.entity.system.SysResource;
import com.springBoot.springBootSysCore.modules.entity.system.SysRole;
import com.springBoot.springBootSysCore.modules.entity.system.SysUser;
import com.springBoot.springBootSysCore.modules.repository.system.SysResourceRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysRoleRepository;
import com.springBoot.springBootSysCore.modules.repository.system.SysUserRepository;
import com.springBoot.springBootSysCore.modules.shiro.SystemAuthorizingRealm.Principal;

/**
 * 用户工具类
 * @author ThinkGem
 * @version 2013-12-05
 */
public class UserUtils {
	private static SysUserRepository sysUserRepository = SpringContextHolder.getBean(SysUserRepository.class);
	private static SysResourceRepository sysResourceRepository = SpringContextHolder.getBean(SysResourceRepository.class);
	private static SysRoleRepository sysRoleRepository = SpringContextHolder.getBean(SysRoleRepository.class);
	
	public static final String USER_CACHE = "userCache";
	public static final String USER_CACHE_ID_ = "id_";
	public static final String USER_CACHE_LOGIN_NAME_ = "ln";
	public static final String USER_CACHE_LIST_BY_OFFICE_ID_ = "oid_";
	
	public static final String CACHE_AUTH_INFO = "authInfo";
	public static final String CACHE_ROLE_LIST = "roleList";
	public static final String CACHE_MENU_LIST = "menuList";
	
	/**
	 * 根据ID获取用户
	 * @param id
	 * @return 取不到返回null
	 */
	public static SysUser get(String id){
		SysUser user = (SysUser)CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + id);
		if (user ==  null){
			try {
				user = sysUserRepository.getOne(id);
				if (user == null || StringUtils.isBlank(user.getId())){
					return null;
				}
				user.setRoleList(sysRoleRepository.findAll(new Specification<SysRole>() {
					@Override
					public Predicate toPredicate(Root<SysRole> root,
												 CriteriaQuery<?> query, CriteriaBuilder cb) {
//					final Path<String> nameP = root.get("name");
						List<Predicate> list=new ArrayList<Predicate>();
//					if(StringUtils.isNotBlank(sysOrganizationClass.getName())){
//						Predicate P_name=cb.like(nameP.as(String.class), "%"+sysOrganizationClass.getName()+"%");
//						list.add(P_name);
//					}

//					final Path<String> defalutUsersId = root.get("defalutUsers").get("id");
//					if(sysUser.getDefalutRole()!=null && StringUtils.isNotBlank(sysUser.getDefalutRole().getCode())){
//						Predicate P_defalutRoleCode=cb.equal(defalutRoleCodeP.as(String.class),sysUser.getDefalutRole().getCode());
//						list.add(P_defalutRoleCode);
//					}
//					list.add(cb.equal(defalutUsersId.as(String.class), id));


//					SysUser  logUser = AppUtils.getSessionUser();
//					ListJoin<SysUser, SysOrganization> orgIdP= root.join(root.getModel().getList("orgList",SysOrganization.class) , JoinType.LEFT);
//					List<String> orgli = sysOrganizationRepositories.getOrgIdByUser(logUser.getId());
//					orgli.add("");//处理没有机构的情况
//					list.add(cb.or(orgIdP.get("id").as(String.class).in(orgli),orgIdP.get("id").as(String.class).isNull()));
						/**按部门机构查询--页面已注释**/
				/*if(StringUtils.isNotBlank(sysUser.getOrgString())){
					ListJoin<SysUser, SysOrganization> orgIdP= root.join(root.getModel().getList("orgList",SysOrganization.class) , JoinType.LEFT);
					Predicate P_orgId = cb.equal(orgIdP.get("id").as(String.class),sysUser.getOrgString());
					list.add(P_orgId);
				}	*/
						/**按班级查询--页面已注释**/
				/*if(StringUtils.isNotBlank(orgClassString)){
					ListJoin<SysUser, SysOrganizationClass> orgIdP= root.join(root.getModel().getList("organizationClass",SysOrganizationClass.class) , JoinType.LEFT);
					Predicate P_orgId = cb.equal(orgIdP.get("id").as(String.class),orgClassString);
					list.add(P_orgId);
				}	*/

						ListJoin<SysRole, SysUser> userIdP= root.join(root.getModel().getList("defalutUsers",SysUser.class) , JoinType.LEFT);
						String userId = sysUserRepository.findOne(id).getId();
						list.add(cb.equal(userIdP.get("id").as(String.class),userId));
						query.where(list.toArray(new Predicate[list.size()]));
						return query.getRestriction();
					}
				}));
				CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
				CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getAccount(), user);
			}catch (Exception e){
				//换服务器出现异常
				e.printStackTrace();
				SecurityUtils.getSubject().logout();
				return null;
			}
		}
		return user;
	}
	
	/**
	 * 根据登录名获取用户
	 * @param account
	 * @return 取不到返回null
	 */
	public static SysUser getByAccount(String account){
		SysUser user = (SysUser)CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_ + account);
		if (user == null){
//			user= new SysUser();
//			user.setAccount(account);
			user=sysUserRepository.findByAccount(account);
			if (user == null){
				return null;
			}
			SysUser finalUser = user;
			user.setRoleList(sysRoleRepository.findAll(new Specification<SysRole>() {
				@Override
				public Predicate toPredicate(Root<SysRole> root,CriteriaQuery<?> query, CriteriaBuilder cb) {
					List<Predicate> list=new ArrayList<Predicate>();
					ListJoin<SysRole, SysUser> userIdP= root.join(root.getModel().getList("defalutUsers",SysUser.class) , JoinType.LEFT);
					String userId = sysUserRepository.findOne(finalUser.getId()).getId();
					list.add(cb.equal(userIdP.get("id").as(String.class),userId));
					query.where(list.toArray(new Predicate[list.size()]));
					return query.getRestriction();
				}
			}));
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getAccount(), user);
		}
		return user;
	}
	
	/**
	 * 清除当前用户缓存
	 */
	public static void clearCache(){
		removeCache(CACHE_AUTH_INFO);
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_MENU_LIST);
		UserUtils.clearCache(getUser());
	}
	
	/**
	 * 清除指定用户缓存
	 * @param user
	 */
	public static void clearCache(SysUser user){
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getAccount());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getOldLoginName());
	}
	
	/**
	 * 获取当前用户
	 * @return 取不到返回 new User()
	 */
	public static SysUser getUser(){
		Principal principal = getPrincipal();
		if (principal!=null){
			SysUser user = get(principal.getId());
			if (user != null){
				return user;
			}
			return new SysUser();
		}
		// 如果没有登录，则返回实例化空的User对象。
		return new SysUser();
	}

	/**
	 * 获取当前用户角色列表--不是默认角色
	 * @return
	 */
	public static List<SysRole> getRoleList(){
		@SuppressWarnings("unchecked")
		List<SysRole> roleList = (List<SysRole>)getCache(CACHE_ROLE_LIST);
		if (roleList == null){
			SysUser user = getUser();
			//数据权限过滤
//			SysRole role = new SysRole();
//			role.getSqlMap().put("dsf", SysBaseService.dataScopeFilter(user.getCurrentUser(), "o", "u"));
			roleList = sysRoleRepository.findAll(new Specification<SysRole>() {
				@Override
				public Predicate toPredicate(Root<SysRole> root,CriteriaQuery<?> query, CriteriaBuilder cb) {
					List<Predicate> list=new ArrayList<Predicate>();
					ListJoin<SysRole, SysUser> userIdP= root.join(root.getModel().getList("users",SysUser.class) , JoinType.LEFT);
					String userId = sysUserRepository.findOne(user.getId()).getId();
					list.add(cb.equal(userIdP.get("id").as(String.class),userId));
					query.where(list.toArray(new Predicate[list.size()]));
					return query.getRestriction();
				}
			});
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}
	
	/**
	 * 获取当前用户授权菜单
	 * @return
	 */
	public static List<SysResource> getMenuList(){
		@SuppressWarnings("unchecked")
		List<SysResource> menuList = (List<SysResource>)getCache(CACHE_MENU_LIST);
		if (menuList == null){
			SysUser user = getUser();
			menuList = sysResourceRepository.findAll(new Specification<SysResource>() {
				@Override
				public Predicate toPredicate(Root<SysResource> root,CriteriaQuery<?> query, CriteriaBuilder cb) {
					List<Predicate> list=new ArrayList<Predicate>();
					ListJoin<SysResource, SysRole> roleIdP= root.join(root.getModel().getList("roles",SysRole.class) , JoinType.LEFT);
					List<String> roleLi = sysRoleRepository.findRoleIdByUser(user.getId());
					if(user.getDefalutRole()!=null){
						if(!roleLi.contains(user.getDefalutRole().getId())){
							roleLi.add(user.getDefalutRole().getId());
						}
					}
					roleLi.add("");//处理用户没有角色的情况
					list.add(cb.or(roleIdP.get("id").as(String.class).in(roleLi),roleIdP.get("id").as(String.class).isNull()));
					query.where(list.toArray(new Predicate[list.size()]));
					return query.getRestriction();
				}
			});
			putCache(CACHE_MENU_LIST, menuList);
		}
		return menuList;
	}
	
	
	/**
	 * 获取授权主要对象
	 */
	public static Subject getSubject(){
		return SecurityUtils.getSubject();
	}
	
	/**
	 * 获取当前登录者对象
	 */
	public static Principal getPrincipal(){
		try{
			Subject subject = SecurityUtils.getSubject();
			if(subject.getPrincipal() instanceof  String){
				return  new Principal(UserUtils.getByAccount(subject.getPrincipal().toString()),true);
			}

//			try {
				Principal principal = (Principal)subject.getPrincipal();
				if (principal != null){
					return principal;
				}
//			}catch (ClassCastException e){
//				return  new Principal(UserUtils.getByAccount(subject.getPrincipal().toString()),true);
//			}
//			subject.logout();
		}catch (UnavailableSecurityManagerException e) {
			
		}catch (InvalidSessionException e){
			
		}
		return null;
	}
	
	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			if (session != null){
				return session;
			}
//			subject.logout();
		}catch (InvalidSessionException e){
			
		}
		return null;
	}
	
	// ============== User Cache ==============
	
	public static Object getCache(String key) {
		return getCache(key, null);
	}
	
	public static Object getCache(String key, Object defaultValue) {
//		Object obj = getCacheMap().get(key);
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
//		getCacheMap().put(key, value);
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
//		getCacheMap().remove(key);
		getSession().removeAttribute(key);
	}
	
//	public static Map<String, Object> getCacheMap(){
//		Principal principal = getPrincipal();
//		if(principal!=null){
//			return principal.getCacheMap();
//		}
//		return new HashMap<String, Object>();
//	}
	
}
